package com.yugao.fintech.antelope.createproject;

import cn.hutool.core.io.FileUtil;
import com.yugao.fintech.framework.assistant.utils.RegexUtils;
import com.yugao.fintech.framework.assistant.utils.file.FileUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 执行当前类可以生成 {@link CreateProjectProperties} 中配置的目标工程
 *
 
 */
@Component
public class CreateProjectRunner implements ApplicationRunner {
    @Autowired
    private CreateProjectProperties createProjectProperties;
    // 工程包名
    private static final String projectStartPackageName = "com.yugao.fintech.antelope";
    // 工程的工程名字简写 相当于每个模块的前缀
    private static final String projectStartNameShort = "draper-antelope";
    // 工程的工程名 = 顶级模块名称
    private static final String projectStartName = "draper-antelope";
    private static final String pomArtifactId = "draper-antelope";
    // 拷贝时候需要排除的文件
    private static final List<String> copyExcludeFiles = new ArrayList<String>() {{
        // 拷贝文件时候会排除当前目录下的 **/target
        add("**" + File.separator + "target");
        add("**" + File.separator + "node_modules");
        add("logs");
        add("pull_submodule.sh");
        add("update_submodule.sh");
        add("**" + File.separator + "LICENSE");
        add("LICENSE");
        add(".idea");
        add(".git");
        add("**" + File.separator+ ".js");
        add("**" + File.separator+ ".html");
        add("**" + File.separator+ ".git");
        add("**" + File.separator+ ".idea");
    }};

    @Override
    public void run(ApplicationArguments args) throws Exception {
        String projectStartPackagePath = packageNameToPath(projectStartPackageName);
        String newPackagePath = packageNameToPath(createProjectProperties.packageName);
        // 参数为空 获取当前项目的根路径
        String currentProjectPath = System.getProperty("user.dir");
        String currentProjectRootPath = currentProjectPath.substring(0, currentProjectPath.lastIndexOf(File.separator));
        String newProjectPath = currentProjectRootPath + File.separator + createProjectProperties.projectName;
        System.out.println("currentProjectRootPath: " + currentProjectRootPath);
        System.out.println("currentProjectPath: " + currentProjectPath);
        System.out.println("newProjectPath: " + newProjectPath);

        List<String> allFile = FileUtils.getAllFile(currentProjectPath, true, getExcludeFilePathReg());
        for (String filePath : allFile) {
            String projectFilePath = filePath
                    .replace(currentProjectRootPath + File.separator + projectStartName + File.separator, "");
            File sourceFile = new File(filePath);

            String newPath = (newProjectPath + File.separator + projectFilePath)
                    .replace(projectStartPackagePath, newPackagePath)
                    .replace(projectStartNameShort, createProjectProperties.projectNameShort);
            File targetFile = new File(newPath);
            if (sourceFile.isDirectory()) {
                if (!targetFile.exists()) {
                    if (!targetFile.mkdirs()) {
                        System.out.println("路径创建失败, " + targetFile);
                    }
                }
                continue;
            }
            FileUtil.copyFile(sourceFile, targetFile);
        }

        List<String> newProjectFiles = FileUtils.getAllFile(newProjectPath, true, null);
        for (String newProjectFile : newProjectFiles) {
            File file = new File(newProjectFile);
            if (file.isFile()) {
                if (isBinary(file)) {
                    // System.out.println("检查到二进制文件, 不做任何处理, path = " + newProjectFile);
                    continue;
                }
            }
            StopWatch stopWatch = StopWatch.createStarted();
            if (file.getName().contains("pom.xml")) {
                FileUtils.replaceText(newProjectFile, "<artifactId>" + pomArtifactId + "</artifactId>",
                        "<artifactId>" + createProjectProperties.pomArtifactId + "</artifactId>");
                FileUtils.replaceText(newProjectFile, projectStartNameShort, createProjectProperties.projectNameShort);
            } else {
                FileUtils.replaceText(newProjectFile, projectStartName, createProjectProperties.projectName);
                FileUtils.replaceText(newProjectFile, projectStartPackageName, createProjectProperties.packageName);
                FileUtils.replaceText(newProjectFile, projectStartNameShort, createProjectProperties.projectNameShort);
            }
            System.out.println("replace content time: " + stopWatch.getTime(TimeUnit.MILLISECONDS) + "ms" + ", new file path: " + newProjectFile);
        }
    }

    public static boolean isBinary(File file) {
        boolean isBinary = false;
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(file);
            long len = file.length();
            for (int j = 0; j < (int) len; j++) {
                int t = fin.read();
                if (t < 32 && t != 9 && t != 10 && t != 13) {
                    isBinary = true;
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (fin != null) {
                try {
                    fin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return isBinary;
    }

    private static String packageNameToPath(String packageName) {
        return packageName.replace(".", File.separator);
    }

    /**
     * 获取排除路径的正则表达式
     */
    private static List<String> getExcludeFilePathReg() throws IOException {
        List<String> regFilePaths = new ArrayList<>();
        File directory = new File("");
        String currentProjectRootPath = directory.getCanonicalPath().substring(0, directory.getCanonicalPath().lastIndexOf(File.separator));;

        for (String excludeFile : copyExcludeFiles) {
            String path = currentProjectRootPath + File.separator + excludeFile;
            path = path.replace("\\", "\\\\");
            String regPath = RegexUtils.getRegex(path);
            regFilePaths.add(regPath);
        }
        return regFilePaths;
    }
}
